#include "xs_def.h"
#include "xs_time.h"

#ifndef isascii
#define isascii(x) 1
#endif /* !defined isascii */

#ifndef ZDUMP_LO_YEAR
#define ZDUMP_LO_YEAR	(-500)
#endif /* !defined ZDUMP_LO_YEAR */

#ifndef ZDUMP_HI_YEAR
#define ZDUMP_HI_YEAR	2500
#endif /* !defined ZDUMP_HI_YEAR */

#ifndef MAX_STRING_LENGTH
#define MAX_STRING_LENGTH	1024
#endif /* !defined MAX_STRING_LENGTH */

#ifndef TRUE
#define TRUE		1
#endif /* !defined TRUE */

#ifndef FALSE
#define FALSE		0
#endif /* !defined FALSE */

#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS	0
#endif /* !defined EXIT_SUCCESS */

#ifndef EXIT_FAILURE
#define EXIT_FAILURE	1
#endif /* !defined EXIT_FAILURE */

#ifndef SECSPERMIN
#define SECSPERMIN	60
#endif /* !defined SECSPERMIN */

#ifndef MINSPERHOUR
#define MINSPERHOUR	60
#endif /* !defined MINSPERHOUR */

#ifndef SECSPERHOUR
#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
#endif /* !defined SECSPERHOUR */

#ifndef HOURSPERDAY
#define HOURSPERDAY	24
#endif /* !defined HOURSPERDAY */

#ifndef EPOCH_YEAR
#define EPOCH_YEAR	1970
#endif /* !defined EPOCH_YEAR */

#ifndef TM_YEAR_BASE
#define TM_YEAR_BASE	1900
#endif /* !defined TM_YEAR_BASE */

#ifndef DAYSPERNYEAR
#define DAYSPERNYEAR	365
#endif /* !defined DAYSPERNYEAR */

#ifndef isleap
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#endif /* !defined isleap */

#ifndef isleap_sum
/*
** See tzfile.h for details on isleap_sum.
*/
#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
#endif /* !defined isleap_sum */

/* Return 1 if YEAR + TM_YEAR_BASE is a leap year.  */
static inline int
leapyear (long int year)
{
  /* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
     Also, work even if YEAR is negative.  */
  return
    ((year & 3) == 0
     && (year % 100 != 0
     || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
}

static const char *
tformat(void)
{
    if (0.5 == (time_t) 0.5) {	/* floating */
        if (sizeof (time_t) > sizeof (double))
            return "%Lg";
        return "%g";
    }
    if (0 > (time_t) -1) {		/* signed */
        if (sizeof (time_t) > sizeof (long))
            return "%lld";
        if (sizeof (time_t) > sizeof (int))
            return "%ld";
        return "%d";
    }
    if (sizeof (time_t) > sizeof (unsigned long))
        return "%llu";
    if (sizeof (time_t) > sizeof (unsigned int))
        return "%lu";
    return "%u";
}


struct tm *
my_localtime(time_t * tp)
{
    register struct tm *	tmp;

    tmp = localtime(tp);
    if (tp != NULL && tmp != NULL) {
        struct tm	tm;
        register time_t	t;

        tm = *tmp;
        t = mktime(&tm);
        if (t - *tp >= 1 || *tp - t >= 1) {
            (void) fflush(stdout);
            //(void) fprintf(stderr, "\n%s: ", progname);
            (void) fprintf(stderr, tformat(), *tp);
            (void) fprintf(stderr, " ->");
            (void) fprintf(stderr, " year=%d", tmp->tm_year);
            (void) fprintf(stderr, " mon=%d", tmp->tm_mon);
            (void) fprintf(stderr, " mday=%d", tmp->tm_mday);
            (void) fprintf(stderr, " hour=%d", tmp->tm_hour);
            (void) fprintf(stderr, " min=%d", tmp->tm_min);
            (void) fprintf(stderr, " sec=%d", tmp->tm_sec);
            (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
            (void) fprintf(stderr, " -> ");
            (void) fprintf(stderr, tformat(), t);
            (void) fprintf(stderr, "\n");
        }
    }
    return tmp;
}

void dumptime(register const struct tm *	timeptr)
{
    static const char	wday_name[][3] = {
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    };
    static const char	mon_name[][3] = {
        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
    register const char *	wn;
    register const char *	mn;
    register int		lead;
    register int		trail;

    if (timeptr == NULL) {
        (void) printf("NULL");
        return;
    }
    /*
    ** The packaged versions of localtime and gmtime never put out-of-range
    ** values in tm_wday or tm_mon, but since this code might be compiled
    ** with other (perhaps experimental) versions, paranoia is in order.
    */
    if (timeptr->tm_wday < 0 || timeptr->tm_wday >=
        (int) (sizeof wday_name / sizeof wday_name[0]))
            wn = "???";
    else		wn = wday_name[timeptr->tm_wday];
    if (timeptr->tm_mon < 0 || timeptr->tm_mon >=
        (int) (sizeof mon_name / sizeof mon_name[0]))
            mn = "???";
    else		mn = mon_name[timeptr->tm_mon];
    (void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
        wn, mn,
        timeptr->tm_mday, timeptr->tm_hour,
        timeptr->tm_min, timeptr->tm_sec);
#define DIVISOR	10
    trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
    lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
        trail / DIVISOR;
    trail %= DIVISOR;
    if (trail < 0 && lead > 0) {
        trail += DIVISOR;
        --lead;
    } else if (lead < 0 && trail > 0) {
        trail -= DIVISOR;
        ++lead;
    }
    if (lead == 0)
        (void) printf("%d", trail);
    else	(void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
}
